package com.gzw.jackyweather.service;

import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by JACKYGUO on 2017/1/12.
 * <p>
 * 异步下载任务
 */

//AsyncTask的三个参数，第一表示传给AsyncTask用的参数，第二个表示进度，第三个表示返回的结果

public class DownLoadTask extends AsyncTask<String, Integer, Integer> {

    public final int TYPE_SUCCESS = 0;
    public final int TYPE_FAILED = 1;
    public final int TYPE_PAUSED = 2;
    public final int TYPE_CANCELED = 3;

    private DownLoadListener listener;

    //是否取消
    private boolean isCancel = false;

    //是否暂停
    private boolean isPaused = false;

    //历史字节数
    private int lastProgress;

    //总字节长度
    private long cententLenght;
    //下载字节长度
    private long count;

    public DownLoadTask(DownLoadListener listener) {
        this.listener = listener;
    }


    //后台执行下载的逻辑
    @Override
    protected Integer doInBackground(String... params) {

        InputStream is = null;

        //随机文件读取
        RandomAccessFile savedFile = null;
        File file = null;
        try {

            long downLoadLenght = 0;
            String downLoadUrl = params[0];//获取下载路径
            String fileName = downLoadUrl.substring(downLoadUrl.lastIndexOf("/"));
            //获得下载文件保存路径
            String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
            file = new File(directory + fileName);
            if (file.exists()) {
                downLoadLenght = file.length();
            }

            //获得内容的长度
            cententLenght = getContentLength(downLoadUrl);
            if (cententLenght == 0) {
                return TYPE_FAILED;
            } else if (cententLenght == downLoadLenght) {
                //已下载字节和文件总字节相等，说明已经下载完成
                return TYPE_SUCCESS;
            }

            //创建连接
            OkHttpClient client = new OkHttpClient();
            //创建请求，addHeader的作用是通知要从哪个字节开始下载。
            Request request = new Request.Builder()
                    .addHeader("RANGE", "bytes=" + downLoadLenght + "-")
                    .url(downLoadUrl)
                    .build();
            //发送请求获得返回的结果
            Response response = client.newCall(request).execute();
            if (response != null) {
                is = response.body().byteStream();
                //"rw"表示打开以便读写或者写入。如果没有该文件就创建
                savedFile = new RandomAccessFile(file, "rw");
                //设置在指定位置开始写入
                savedFile.seek(downLoadLenght);
                byte[] b = new byte[1024];
                int total = 0;
                int len;
                while ((len = is.read(b)) != -1) {//一次读取1024个字节。
                    if (isCancel) {//在读取过程中取消，就返回取消类型，如果是暂停就返回暂停类型，否则一直写入文件，更新进度
                        return TYPE_CANCELED;
                    } else if (isPaused) {
                        return TYPE_PAUSED;
                    } else {
                        total += len;
                        savedFile.write(b, 0, len);
                        int progress = (int) ((total + downLoadLenght) * 100 / cententLenght);
                        count = total + downLoadLenght;
                        publishProgress(progress);
                    }
                }
                response.close();
                return TYPE_SUCCESS;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }

                if (savedFile != null) {
                    savedFile.close();
                }

                if (isCancel && file != null) {
                    file.delete();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return TYPE_FAILED;
    }


    /**
     * 刷新进度
     *
     * @param values
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        int progress = values[0];

        ///当前进度如果大于历史的进度，就更新UI
        if (progress > lastProgress) {
            listener.onProgress(progress, count, cententLenght);
            lastProgress = progress;
        }
    }


    /**
     * 返回请求处理的结果。
     *
     * @param integer
     */
    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);

        switch (integer) {
            case TYPE_SUCCESS:
                listener.onSuccess();
                break;
            case TYPE_FAILED:
                listener.onFailed();
                break;
            case TYPE_PAUSED:
                listener.onPaused();
                break;
            case TYPE_CANCELED:
                listener.onCanceled();
                break;
        }
    }

    //暂停下载
    public void pausedDownLoad() {
        isPaused = true;
    }

    //取消下载
    public void cancelDownLoad() {
        isCancel = true;
    }


    //获取下载内容的长度
    private long getContentLength(String downLoadUrl) throws IOException {

        //初始化一个client
        OkHttpClient client = new OkHttpClient();
        //创建一个连接
        Request request = new Request.Builder().url(downLoadUrl).build();
        //发送一个请求，获得响应结果
        Response respose = client.newCall(request).execute();
        if (respose != null && respose.isSuccessful()) {
            //获取下载内容的长度
            long cententLength = respose.body().contentLength();
            respose.close();
            return cententLength;
        }
        return 0;
    }
}
